#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <unistd.h>
#include <cstring>
using namespace std;

#define nr_g_arg  64
const int basesize = 1024;
const int nr_env = 64;
char *command;

char *g_argv[nr_g_arg];
int g_argc;

// 全局的当前工作路径
char pwd[basesize];
char pwdPattern[basesize];
// 我的系统的环境变量
char *genv[nr_env];


const char* GetHost(){
    string host = getenv("HOSTNAME");
    return host.empty() ? "None" : host.c_str();
}

const char* GetUsr(){
    string usr = getenv("USER");
    return usr.empty() ? "None" : usr.c_str();
}

const char* GetPwd(){
    if(nullptr == getcwd(pwd, sizeof(pwd))){
        return "None";
    }	    
    snprintf(pwdPattern,sizeof(pwdPattern),"PWD=%s", pwd);
    putenv(pwdPattern);
    return pwd; 
}

void PrintCommandPrompt(){
    const char* usr = GetUsr();
    const char* host = GetHost();
    const char* pwd = GetPwd();
    char CommandLine[basesize];
    snprintf(CommandLine, basesize, "[%s@%s %s]# "\
		    , GetUsr(), host, GetPwd());
    printf("%s",CommandLine);
    fflush(stdout);
}
bool GetCommand(){
    command = (char*)malloc(sizeof(char)*basesize);
    
    if(nullptr != fgets(command, basesize, stdin)){
        //读取后包含了\n
        if(strlen(command)==1) return false;
        command[strlen(command)-1] = '\0';//替换为 0
        return true;
    }
    return false;
    

}


void ParseCommand(){
    int i = 0;
    const char* delimiter = " ";
    g_argv[i++] = strtok(command,delimiter);
    
    while((bool)(g_argv[i++]=strtok(nullptr,delimiter)));
    i--;
    g_argc = i;
}
void debug(){
    printf("g_argc : %d\n", g_argc);	
    for(int i = 0; g_argv[i]; ++i){
	printf("%s ",g_argv[i]);
    }   
    
}

bool ExecuteCommand(){

	
    pid_t id = fork();
    if(id == 0){
        //子进程
	execvp(g_argv[0], g_argv);
	//程序替换失败
	exit(1);
    }
    //父进程
    else if(id > 0){
	int status = 0;
	pid_t rid = waitpid(id, &status, 0);
	if(rid > 0)
	{
	    return true;
	}
	else {return false;}
    }
    else{
	return false;
    }



}


void InitEnv(){
    //将 bash 的环境变量引入到 自己的 shell中
    extern char** environ;
    for(int i = 0; environ[i]; ++i){
        g_env[i] = (char*)malloc(strlen(environ[i])+1);
	// strncpy(g_env[i], environ[i],strlen(environ[i]+1));
        memcpy(g_env[i], environ[i]);
    }
    g_env[i] = nullptr;
}
void AddEnv(const char *item){
    int index = 0;
    while(g_env[index]){index++;}
    
    g_env[index] = (char*)malloc(strlen(item)+1);
    strncpy(g_env[index], item, strlen(item)+1);
    g_env[++index] = nullptr;
}

bool CheckBuiltInCommand(){
    //对于 内建命令 不需要也不能让子进程运行
    //只有外部命令需要子进程，我父进程管理好就行了
    if(strcmp(g_argv[0], "cd") == 0){
         if(2 == g_argc){
             chdir(g_argv[1]);
	 }
         return true;
    }
    else if(0==strcmp(g_argv[0], "export")){
         if(2 == g_argc){
	      AddEnv(g_argv[1]);
	 }
	 return true;    
    }
    else if()
    return false;
}
int main(){
    // 模拟bash将配置文件读取到环境变量中
    InitEnv();
    while(true){
	//命令行+命令行提示符 格式
	PrintCommandPrompt();
	//用户输入命令，将其给到全局变量command
	if(!GetCommand()){
             continue;		
	}

	//分析用户指令，将指令分好词块
	ParseCommand();
	//debug();
        if(CheckBuiltInCommand()){continue;}
        ExecuteCommand(); 
    }


    return 0;
}
